﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Threading.Tasks;
using Language.Stub;
using Microsoft.VisualStudio.Text;
using Red.Scripts.Defines;
using Defines = Red.Scripts.Defines.Scc;

namespace Language.Scc
{
    [Export]
    public sealed class Connection : IPartImportsSatisfiedNotification
    {
        #region Private Data

        private SolutionParser _solutionParser;
        private FileParser _fileParser;

        Defines.Launcher _launcher;
        Defines.Connection _connection;
        Defines.Connector _connector;

        #endregion Private Data

        #region Imports

        [Import]
        public Database Database { get; set; }

        [Import( typeof( CompilerPane ) )]
        public ILogPane Log { get; set; }

        [Import]
        private Settings Settings { get; set; }

        #endregion Imports

        #region C-Tor

        public Connection()
        {
            _launcher = new Defines.Launcher();
            _connection = new Defines.Connection();
            _connector = new Defines.Connector( _launcher, _connection );

            _launcher.Log += OnLog;
            _connection.Log += OnLog;
        }

        #endregion C-Tor

        #region Public Methods

        public async Task Parse( string file, ITextSnapshot data, bool force = false )
        {
            // If there are ever hit we need to wait for imports to be fulfilled before we allow this function to be called
            Debug.Assert( _launcher != null );
            Debug.Assert( _connection != null );
            Debug.Assert( _connector != null );
            Debug.Print( $"Parsing '{file}' on thread: {System.Threading.Thread.CurrentThread.ManagedThreadId}" );

            if ( !_launcher.IsRunning && _launcher.SearchData.SearchOrder == null )
            {
                _launcher.SearchData.SearchOrder = (IEnumerable<SccSearchOrder>)Settings[ Setting.SccSearchOrder ];
                _launcher.SearchData.CustomFilePath = (string)Settings[ Setting.SccCustomSearchPath ];
            }

            if ( !await _connector.Connect() )
                return;

            await _solutionParser.RequestParse( file );
            await _solutionParser.ParseTask.Task;

            await _fileParser.Parse( file, data );
        }

        public async Task ReparseSolution( string anyScriptFilePath )
        {
            if( _solutionParser.InitializationComplete && _solutionParser.InitializationSent )
            {
                _solutionParser.Reset();
                await _solutionParser.RequestParse( anyScriptFilePath );
                await _solutionParser.ParseTask.Task;
            }
        }

        public void Disconnect()
        {
            _solutionParser.Reset();
            _connector.Disconnect();
            _launcher.ResetSearchData();
        }

        #endregion Public Methods

        #region Event Handlers

        private void OnLog( string text )
        {
            Log?.PrintLine( text );
        }

        #endregion Event Handlers

        #region IPartImportsSatisfiedNotification

        public void OnImportsSatisfied()
        {
            _solutionParser = new SolutionParser( _connection, Database );
            _fileParser = new FileParser( _connection, Database ) { Log = Log };
        }

        #endregion IPartImportsSatisfiedNotification
    }
}
